package graph;

/**
 *
 * @author Alykam e Guilherme
 */

import graphCORE.GraphInterface;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;


public class Graph implements GraphInterface{
    
    /*
     * 
     * Classe que instancia grafo com lista de vértices e funções relacionadas. 
     */
    
    /*
     * lista de vértices no grafo.
     */
    private HashMap<Integer, Vertex> vertexList= new HashMap<Integer, Vertex>();

    /*
     * método que retorna a ordem do grafo
     */
    @Override
    public int getOrder() {
        return this.vertexList.size();
    }

    /*
     * método que retorna o tamanho do grafo
     */
    @Override
    public int getSize() {
        int edges=0;
        ArrayList<Vertex> vertexes=new ArrayList<Vertex>(this.vertexList.values());
        
        for (int i=0;i<vertexes.size();i++){
            edges+=this.vertexList.get(vertexes.get(i).getId()).getVertexAdjList().size();              
        }
        return edges/2;
    }
    
    /*
     * método que retorna a lista de vértices
     */
    public HashMap<Integer, Vertex> getVertexList(){
        return this.vertexList;
    }

    /*
     * método que recebe um id de vértice e retorna o objeto vértice com o
     * mesmo id
     */
    public Vertex getVertexById(int id){
        return this.vertexList.get(id);
        
    }
    
    /*
     * método que retorna a ordem do grafo
     */
    @Override
    public int V() {
        return this.vertexList.size();
    }

    /*
     * método que retorna o tamanho do grafo
     */
    @Override
    public int E() {
        return this.getSize();
    }

    /*
     * método que adiciona um vértice na lista de vértices
     */
    @Override
    public void addVertex(int id) {
        this.vertexList.put(id, new Vertex(id));        
    }

    
     /*
      * método que adiciona aresta aos dois vértices
      */
    @Override
    public void addEdge(int vi, int vj) {  
        if((this.vertexList.get(vi)!=null)&&(this.vertexList.get(vj)!=null)){
            this.vertexList.get(vi).getVertexAdjList().add(vj);
            this.vertexList.get(vj).getVertexAdjList().add(vi);
        }
    }

   
    /*
     * método que verifica se vértices são adjacentes, 
     * recebe ids dos dois vértices
     */
    @Override
    public boolean adjacent(int vi, int vj) {
        if (this.vertexList.get(vi).isAdjacent(vj))
            return true;
        return false;
    }

    /*
     * remove vértice, recebe id do vértice a ser removido
     * remove arestas conectadas no vértice
     */
    @Override
    public void removeVertex(int id) {
        this.vertexList.remove(id);
        for (Map.Entry<Integer, Vertex> entry : vertexList.entrySet()) {
            Integer integer = entry.getKey();
            for (int i = 0; i < this.vertexList.get(integer).getVertexAdjList().size(); i++) {
                 if(this.vertexList.get(integer).isAdjacent(id)){
                     if(this.vertexList.get(integer).getVertexAdjList().get(i).equals(id))
                         this.vertexList.get(integer).getVertexAdjList().remove(i);  
                 }
            }     
            
        }
    }
    /*
     * remove aresta, recebe id de dois vértices.
     */
    @Override
    public void removeEdge(int vi, int vj) {
        
        for (int i=0;i<=this.vertexList.get(vi).getVertexAdjList().size();i++){
            if(this.vertexList.get(vi)!=null)
                if(this.vertexList.get(vi).getVertexAdjList().get(i)!=null)
                    if(this.vertexList.get(vi).getVertexAdjList().get(i)==vj){
                        this.vertexList.get(vi).removeEdge(i);
                break;}
        }
        for (int i=0;i<=this.vertexList.get(vj).getVertexAdjList().size();i++){
            if(this.vertexList.get(vj)!=null)
                if(this.vertexList.get(vj).getVertexAdjList().get(i)!=null)
                    if(this.vertexList.get(vj).getVertexAdjList().get(i)==vi){
                        this.vertexList.get(vj).removeEdge(i);
                break;}
        }     
          
                
    }
    
    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("Graph [");
        builder.append("vertex=(");
        builder.append(this.vertexList);
        builder.append(")]");       
        return builder.toString();
    }
    
}
